package com.blog.service.Impl;
import com.alibaba.fastjson.JSON;
import com.blog.Event.EventMsgDomain;
import com.blog.SystemMsg.SystemMsgProducer;
import com.blog.Utils.RedisKeyUtil;
import com.blog.bean.domain.Comment;
import com.blog.bean.domain.DiscussPost;
import com.blog.service.CommentService;
import com.blog.service.DiscussPostService;
import com.blog.service.LikeService;
import com.blog.bean.vo.LikeVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

/**
 * @author 任浩
 * @version 1.0
 */

@Service
@Slf4j
public class LikeServiceImpl implements LikeService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private DiscussPostService discussPostService;
    @Autowired
    private SystemMsgProducer systemMsgProducer;
    @Autowired
    private EventMsgDomain eventMsgDomain;
    @Autowired
    private CommentService commentService;

    /**
     * 进行点赞的方法。
     * @param postId
     * @param userID
     * @return
     */
    @Override
    public LikeVO like(String postId, String userID,Integer index) {
        /**
         * 我们点赞使用的redis的数据结构为set。
         * 使用当前的帖子id作为set数据结构的key,
         * 使用用户id作为value值。
         * 我们先进行查看当前用户是否进行了点赞，如果有的话，那么这里就是进行取消点赞操作。
         * 如果没有，那么就是进行点赞操作。
         */
        LikeVO likeVO = new LikeVO();
        //设置帖子的id号，返回给客户端
        likeVO.setPostId(Integer.parseInt(postId));
        SetOperations setOperations = redisTemplate.opsForSet();

        //暂时保存以下帖子的id，用于得到帖子属于哪个用户.
        String temPostId = postId;

        //使用redis工具类得到帖子的key值
        postId = RedisKeyUtil.init(postId);
        Boolean member = setOperations.isMember(postId, userID);
        if(member){
            //进行取消点赞的操作。
            setOperations.remove(postId,userID);
            likeVO.setLikecode(0);
            cancelUserLike(temPostId,1);
        }else {
            //进行点赞的操作。
            setOperations.add(postId,userID);
            likeVO.setLikecode(1);
            addUserLike(temPostId,1);

            //对点赞成功的信息，进行系统通知。
            eventMsgDomain.setFromId(1);
            eventMsgDomain.setConversationId("like");
            eventMsgDomain.setEntity_type(1);
            eventMsgDomain.setUserid(Integer.parseInt(userID));
            eventMsgDomain.setId(Integer.parseInt(temPostId));
            eventMsgDomain.setOperate_type("帖子");

            String msg = JSON.toJSONString(eventMsgDomain);
            systemMsgProducer.producer(msg);
        }

        //统计当前的帖子的点赞的数量
        Long size = setOperations.size(postId);
        likeVO.setLikeCount(size);
        likeVO.setIndex(index);
        likeVO.setStatus(1);

        //更新当前点赞的帖子的热度分数
        //对当前进行加精的帖子进行热度分数更新，把当前的帖子id保存到redis中，然后使用定时线程池，处理业务,完成帖子的热度更新操作。
        //使用redis的set数据结构保存，所有要更新热度的帖子id。
        //点赞，评论，加精都会让帖子的热度更新。
        //得到保存到redis中的key
        Integer id = Integer.parseInt(temPostId);
        String scoreKey = RedisKeyUtil.scoreInit();
        redisTemplate.opsForSet().add(scoreKey,id);

        return likeVO;
    }

    /**
     * 查询一开始的点赞信息。
     * @param id
     * @return
     */
    @Override
    public LikeVO queryLike(Integer id,Integer userId) {
        LikeVO likeVO = new LikeVO();
        //设置帖子的id号，返回给客户端
        likeVO.setPostId(Integer.parseInt(id.toString()));

        SetOperations setOperations = redisTemplate.opsForSet();
        //使用redis工具类得到帖子的key值
        Long size = setOperations.size(RedisKeyUtil.init(id.toString()));
        likeVO.setLikeCount(size);

        likeVO.setStatus(0);
        //只有当用户登录的时候才显示，已点赞还是未点赞。
        if(userId != null){
            //判断当前用户是已点赞还是未点赞。
            Boolean member = setOperations.isMember(RedisKeyUtil.init(id.toString()), userId.toString());
            if(member){
                //当前用户已点赞
                likeVO.setLikecode(1);
            }else {
                //当前用户未点赞。
                likeVO.setLikecode(0);
            }
        }
        return likeVO;
    }


    /**
     * 查询评论的点赞信息
     * @param id
     * @return
     */
    @Override
    public LikeVO commentQueryLike(Integer id,Integer userId) {
        LikeVO likeVO = new LikeVO();
        //设置帖子的id号，返回给客户端
        likeVO.setPostId(Integer.parseInt(id.toString()));

        SetOperations setOperations = redisTemplate.opsForSet();
        //使用redis工具类得到帖子的key值
        Long size = setOperations.size(RedisKeyUtil.commentInit(id.toString()));
        likeVO.setLikeCount(size);

        likeVO.setStatus(0);
        //只有当用户登录的时候才显示，已点赞还是未点赞。
        if(userId != null){
            //判断当前用户是已点赞还是未点赞。
            Boolean member = setOperations.isMember(RedisKeyUtil.commentInit(id.toString()), userId.toString());
            System.out.println("点赞是否成功" + member);
            if(member){
                //当前用户已点赞
                likeVO.setLikecode(1);
            }else {
                //当前用户未点赞。
                likeVO.setLikecode(0);
            }
        }
        return likeVO;
    }

    /**
     * 对评论进行点赞的方法
     * @param postId
     * @param userID
     * @param index
     * @return
     */
    @Override
    public LikeVO commentlike(String postId, String userID, Integer index) {

        LikeVO likeVO = new LikeVO();
        //设置帖子的id号，返回给客户端
        likeVO.setPostId(Integer.parseInt(postId));
        SetOperations setOperations = redisTemplate.opsForSet();

        //暂时保存以下帖子的id，用于得到帖子属于哪个用户.
        String temPostId = postId;

        //使用redis工具类得到帖子的key值
        postId = RedisKeyUtil.commentInit(postId);
        Boolean member = setOperations.isMember(postId, userID);
        if(member){
            //进行取消点赞的操作。
            setOperations.remove(postId,userID);
            likeVO.setLikecode(0);
            cancelUserLike(temPostId,2);
        }else {
            //进行点赞的操作。
            setOperations.add(postId,userID);
            likeVO.setLikecode(1);
            addUserLike(temPostId,2);

            //对点赞成功的信息，进行系统通知。
            eventMsgDomain.setFromId(1);
            eventMsgDomain.setConversationId("like");
            eventMsgDomain.setEntity_type(1);
            eventMsgDomain.setUserid(Integer.parseInt(userID));
            eventMsgDomain.setId(Integer.parseInt(temPostId));
            eventMsgDomain.setOperate_type("评论");

            String msg = JSON.toJSONString(eventMsgDomain);
            systemMsgProducer.producer(msg);

        }
        //统计当前的帖子的点赞的数量
        Long size = setOperations.size(postId);
        likeVO.setLikeCount(size);
        likeVO.setIndex(index);
        likeVO.setStatus(1);

        //通过当前的评论的id得到当前帖子的id。我们添加热度是为了帖子添加热度。
        Comment comment = new Comment();
        comment.setId(Integer.parseInt(temPostId));
        comment = commentService.queryPostByPostId(comment);

        //更新当前点赞的帖子的热度分数
        //对当前进行加精的帖子进行热度分数更新，把当前的帖子id保存到redis中，然后使用定时线程池，处理业务,完成帖子的热度更新操作。
        //使用redis的set数据结构保存，所有要更新热度的帖子id。
        //点赞，评论，加精都会让帖子的热度更新。模拟
        //得到保存到redis中的key
        String scoreKey = RedisKeyUtil.scoreInit();
        redisTemplate.opsForSet().add(scoreKey,comment.getEntityId());

        return likeVO;
    }

    /**
     * 对评论回复点赞的方法。
     * @param postId
     * @param userID
     * @param index
     * @param index2
     * @return
     */
    @Override
    public LikeVO commentReplylike(String postId, String userID, Integer index, Integer index2) {

        LikeVO likeVO = new LikeVO();
        //设置帖子的id号，返回给客户端
        likeVO.setPostId(Integer.parseInt(postId));
        SetOperations setOperations = redisTemplate.opsForSet();

        //暂时保存以下帖子的id，用于得到帖子属于哪个用户.
        String temPostId = postId;

        //使用redis工具类得到帖子的key值
        postId = RedisKeyUtil.commentInit(postId);
        Boolean member = setOperations.isMember(postId, userID);
        if(member){
            //进行取消点赞的操作。
            setOperations.remove(postId,userID);
            likeVO.setLikecode(0);
            cancelUserLike(temPostId,2);
        }else {
            //进行点赞的操作。
            setOperations.add(postId,userID);
            likeVO.setLikecode(1);
            addUserLike(temPostId,2);

            //对点赞成功的信息，进行系统通知。
            eventMsgDomain.setFromId(1);
            eventMsgDomain.setConversationId("like");
            eventMsgDomain.setEntity_type(1);
            eventMsgDomain.setUserid(Integer.parseInt(userID));
            eventMsgDomain.setId(Integer.parseInt(temPostId));
            eventMsgDomain.setOperate_type("回复");


            String msg = JSON.toJSONString(eventMsgDomain);
            systemMsgProducer.producer(msg);
        }
        //统计当前的帖子的点赞的数量
        Long size = setOperations.size(postId);
        likeVO.setLikeCount(size);
        likeVO.setIndex(index);
        likeVO.setIndex2(index2);
        likeVO.setStatus(1);

        //通过当前的评论的id得到当前帖子的id。我们添加热度是为了帖子添加热度。
        Comment comment = new Comment();
        comment.setId(Integer.parseInt(temPostId));
        comment = commentService.queryPostByPostId(comment);

        //更新当前点赞的帖子的热度分数
        //对当前进行加精的帖子进行热度分数更新，把当前的帖子id保存到redis中，然后使用定时线程池，处理业务,完成帖子的热度更新操作。
        //使用redis的set数据结构保存，所有要更新热度的帖子id。
        //点赞，评论，加精都会让帖子的热度更新。
        //得到保存到redis中的key
        String scoreKey = RedisKeyUtil.scoreInit();
        redisTemplate.opsForSet().add(scoreKey,comment.getEntityId());

        return likeVO;
    }

    /**
     * 查询用户的点赞数
     * @param userId
     * @return
     */
    @Override
    public Integer queryUserLike(Integer userId) {
        /**
         * 注意：用户的点赞数，我们使用redis的string数据类型来进行存储，因为我们使用当前的用户id为关键值，
         * 只需要进行对值进行加减操作就行了。因此选用string类型是最合适的。
         */
        //得到用户存储在redis中的关键字。
        String userKey = RedisKeyUtil.userInit(userId.toString());
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //得到当前用户的点赞的数量
        Object size =  valueOperations.get(userKey);
        if(size == null){
            return 0;
        }
        return Integer.parseInt(size.toString());
    }

    /**
     * 添加用户点赞的方法。
     */
    public void addUserLike(String postId,Integer type){
        //通过帖子的id找到帖子属于哪个用户。对用户的点赞数进行加或者减。
        Integer userId = 0;
        if(type == 1){  //查询帖子的用户id
            DiscussPost discussPost = new DiscussPost();
            discussPost.setId(Integer.parseInt(postId));
            discussPost = discussPostService.queryPostByPostId(discussPost); //就可以得到帖子属于哪个用户。
            userId = Integer.parseInt(discussPost.getUserId());
        }
        else if (type == 2){  //查询评论属于哪个用户
            Comment comment = new Comment();
            comment.setId(Integer.parseInt(postId));
            comment = commentService.queryPostByPostId(comment); //就可以得到帖子属于哪个用户。
            userId = comment.getUserId();
        }
        String userKey = RedisKeyUtil.userInit(userId.toString());
        redisTemplate.opsForValue().increment(userKey,1);
    }

    /**
     * 取消用户点赞的方法。
     * @param postId
     */
    public void cancelUserLike(String postId,Integer type){
        //通过帖子的id找到帖子属于哪个用户。对用户的点赞数进行加或者减。
        Integer userId = 0;
        if(type == 1){  //查询帖子的用户id
            DiscussPost discussPost = new DiscussPost();
            discussPost.setId(Integer.parseInt(postId));
            discussPost = discussPostService.queryPostByPostId(discussPost); //就可以得到帖子属于哪个用户。
            userId = Integer.parseInt(discussPost.getUserId());
        }
        else if (type == 2){  //查询评论属于哪个用户
            Comment comment = new Comment();
            comment.setId(Integer.parseInt(postId));
            comment = commentService.queryPostByPostId(comment); //就可以得到帖子属于哪个用户。
            userId = comment.getUserId();
        }
        String userKey = RedisKeyUtil.userInit(userId.toString());
        redisTemplate.opsForValue().decrement(userKey);
    }

}
